/*
 * dataqueue.h
 *
 *  Created on: 2011-8-16
 *      Author: chenl
 *     Purpose:
 *        Note:
 */

#ifndef DATAQUEUE_H_
#define DATAQUEUE_H_

#include "common/common_bytequeue.h"
#include "loki/Singleton.h"
#include "common/protocol.h"

#define MAX_RADARDATAQUEUE_LEN	0x10000
#define MAX_CLIENTDATAQUEUE_LEN 0x1000

typedef CByteQueue<MAX_RADARDATAQUEUE_LEN> RadarDataQueueType;
typedef Loki::SingletonHolder<RadarDataQueueType> RadarDataQueue;
#define CREATE_RADARDATAQUEUE_INSTANCE		RadarDataQueue::Instance
#define GET_RADARDATAQUEUE_INSTANCE 		RadarDataQueue::Instance

class ClientDataQueueType : public CByteQueue<MAX_CLIENTDATAQUEUE_LEN>
{
public:
	enum
	{
		enmLockFree = enmInvalidClientID,
	};
public:
	ClientDataQueueType() : m_nClinetLock(enmLockFree){}
	virtual ClientDataQueueType();
public:
	virtual int32_t Initialize()
	{
		int32_t ret = S_OK;
		ret = CByteQueue<MAX_CLIENTDATAQUEUE_LEN>::Initialize();
		if (0 > ret)
		{
			return -1;
		}
		if (enmLockFree != m_nClinetLock)
		{
			return -1;
		}
	}
public:
		int32_t Push(const uint8_t arrBuf[], uint32_t uLen, ClientID nClientID)
		{
			if (!AquireLock(nClient))
			{
				return E_CLIENT_LOCKED;
			}
			BuffParam buff = {0};
			buff.pBuff = arrBuf;
			buff.len = uLen;
			return CByteQueue<MAX_CLIENTDATAQUEUE_LEN>::Push(buff);
		}
		int32_t Pop(uint8_t *pBuf, uint32_t &uLen, ClientID &nClientID)
		{
			nClientID = m_nClinetLock;
			BuffParam buff = {0};
			int32_t ret = CByteQueue<MAX_CLIENTDATAQUEUE_LEN>::Pop(buff);
			if (CByteQueue<MAX_CLIENTDATAQUEUE_LEN>::IsEmpty())
			{
				ReleaseLock();
			}
			return ret;
		}
		void Clear()
		{
			ReleaseLock();
			CByteQueue<MAX_CLIENTDATAQUEUE_LEN>::Clear();
		}

		ClientID GetCurrentClient() const
		{
			return m_nClinetLock;
		}
private:
	bool AquireLock(ClientID nClientID)
	{
		if (enmLockFree == m_nClinetLock)
		{
			m_nClinetLock = nClientID;
			return true;
		}
		if (m_nClinetLock == nClientID)
		{
			return true;
		}
		return false;
	}
	void ReleaseLock()
	{
		m_nClinetLock = enmLockFree;
	}
	virtual int32_t Push(const BuffParam& buff);
	virtual int32_t Pop(BuffParam& buff);
	virtual int32_t Front(BuffParam& buff) const;

private:
	ClientID m_nClinetLock;
};

typedef Loki::SingletonHolder<ClientDataQueueType> ClientDataQueue;
#define CREATE_CLIENTDATAQUEUE_INSTANCE		ClientDataQueue::Instance
#define GET_CLIENTDATAQUEUE_INSTANCE 		ClientDataQueue::Instance

#endif /* DATAQUEUE_H_ */
